#include <iostream>

using namespace std;
class shape {
public:
    shape() { cout << "shape" << endl; }

    virtual ~shape() {
        cout << "~shape" << endl;
    }
};
class circle : public shape {
public:
    circle() { cout << "circle" << endl; }


    ~circle() {
        cout << "~circle" << endl;
    }
};
class triangle : public shape {
public:
    triangle() { cout << "triangle" << endl; }


    ~triangle() {
        cout << "~triangle" << endl;
    }
};
class rectangle : public shape {
public:
    rectangle() { cout << "rectangle" << endl; }

    ~rectangle() {
        cout << "~rectangle" << endl;
    }
};
class result {
public:
    int *p;
    result() { puts("result()");  p = new int(1);}
    void print() { cout << *p << endl; }
    ~result() { puts("~result()"); delete p; p=nullptr; }
};

struct rwrap {
    result res;
};

result process_shape(const shape &shape1, const shape &shape2) {
    puts("process_shape()");
    return result();
}

void tf1(result && rr) 
{
    puts("tf1()");
}

int main() {
    result res;
    cout << "Test start...." << endl;
    //匿名右值会被立即析构
    process_shape(circle(), triangle());
    cout << "test flag1..." << endl; 
    //将纯右值和右值引用绑定，纯右值的生命周期延长到和右值引用相同
    auto &&r1 = process_shape(circle(), triangle());
    r1.print();
    cout << "test flag2..." << endl; 
    //将纯右值转换为xvalue后再和右值引用绑定，注意此时原值的生命周期并没有得到延
    //长(绑定即被析构)，后续对右值引用的使用将是不安全的(可以绑定到右值引用型参，函数调用返回后再释放原右值)
    auto &&r2 =  std::move(process_shape(circle(), triangle()));
    //r2.print(); //error, 已被析构
    cout << "test flag3..." << endl; 
    //将左值转换为xvalue后再和右值引用绑定，此时原右值不会被立即析构。
    auto &&r3 =  std::move(res);
    r3.print();
    tf1(std::move(res)); //tf1返回后res也不会被西沟
    cout << "test flag4..." << endl;
    //将通过纯右值取成员得到的xvalue和右值引用绑定，那么纯右值的声明周期也得到延长
    auto &&r4 = rwrap().res;
    cout << "test flag5..." << endl;
    //将纯右值转换为xvalue后再和右值引用型参绑定，函数调用返回后再释放原右值
    tf1(std::move(result()));
    cout << "Test finish!!!" << endl;
    return 0;
}

